package imachine.engine;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

class Guard {
	private Guard(int transitionId, Object listener, Method callbackFunc) {
		this.transitionId = transitionId;
		this.listener = listener;
		this.callbackMethod = callbackFunc;
	}

	static Guard createGuard(int transitionId, Object listener,
			String actionName) {
		Guard guard = null;
		if (null != listener && null != actionName) {
			Method method = null;
			try {
				method = listener.getClass().getMethod(actionName, PARAM_TYPES);
				if (method.getReturnType() == Boolean.class
						&& Modifier.isPublic(method.getModifiers())) {
					guard = new Guard(transitionId, listener, method);
				}
			} catch (SecurityException e) {
				//e.printStackTrace();
			} catch (NoSuchMethodException e) {
				//e.printStackTrace();
			}
		}
		return guard;
	}

	boolean satisfied(final Object inContext, Object outContext) {
		Object args[] = { transitionId, inContext, outContext };
		Boolean rtn = new Boolean(false);
		try {
			rtn = Boolean.class.cast(callbackMethod.invoke(listener, args));
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// Shall not reach here
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return rtn.booleanValue();
	}

	private static final Class PARAM_TYPES[] = { Integer.class, Object.class,
			Object.class };

	final int transitionId;
	final Object listener;
	final Method callbackMethod;
}
